package com.zmn.plat.business.impl.msg;

import java.util.*;
import java.util.stream.Collectors;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.fastjson.JSON;
import com.google.common.collect.Maps;
import com.taobao.api.ApiException;
import com.zmn.common.constant.GlobalConsts;
import com.zmn.common.dto2.ResponseDTO;
import com.zmn.common.utils.date.DateUtil;
import com.zmn.common.utils.string.StringUtil;
import com.zmn.mcc.common.dto.staff.StaffDRO;
import com.zmn.mcc.dubbo.interfaces.staff.StaffListRemoteService;
import com.zmn.plat.business.interfaces.dingtalk.DingTalkService;
import com.zmn.plat.business.interfaces.msg.MsgBService;
import com.zmn.plat.business.interfaces.msg.conf.MsgConfBService;
import com.zmn.plat.common.constant.MsgConfConsts;
import com.zmn.plat.common.dictionary.MsgTypeEnum;
import com.zmn.plat.common.exception.PlatException;
import com.zmn.plat.dubbo.dto.msg.MsgDIO;
import com.zmn.plat.dubbo.utils.DubboConsts;
import com.zmn.plat.manager.constant.ZmnSmsConsts;
import com.zmn.plat.manager.dictionary.ZmnSmsDict;
import com.zmn.plat.model.entity.msg.conf.MsgConf;
import com.zmn.plat.model.entity.push.PushInner;
import com.zmn.plat.model.entity.push.ZmnSms;
import com.zmn.plat.model.vo.msg.receive.staff.MsgStaffSimpleVO;
import com.zmn.plat.services.interfaces.msg.conf.MsgConfService;
import com.zmn.plat.services.interfaces.push.PushInfoService;
import com.zmn.plat.services.interfaces.push.ZmnSmsService;

/**
 * 消息管理BServiceImpl
 *
 * @author linfeng
 * @since 2020/06/01 16:15
 */
@Service
public class MsgBServiceImpl implements MsgBService {
    private Logger logger = LoggerFactory.getLogger(MsgBServiceImpl.class);

    @Resource
    MsgConfService msgConfService;

    @Resource
    MsgConfBService msgConfBService;

    @Resource
    PushInfoService pushInfoService;

    @Resource
    private DingTalkService dingTalkService;

    @Resource
    private ZmnSmsService zmnSmsService;

    @Reference(version = DubboConsts.INTERFACE_VERSION, check = false)
    private StaffListRemoteService staffListRemoteService;

    @Value("${spring.profiles.active}")
    private String profiles;

    public static HashMap<String, String> getUri() {
        HashMap<String, String> hashMap = Maps.newHashMap();
        hashMap.put("dev", "http://dev-plat.xiujiadian.com");
        hashMap.put("test", "https://test-plat.xiujiadian.com");
        hashMap.put("prod", "https://plat.xiujiadian.com");
        return hashMap;
    }

    @Override
    public Boolean sendMsg(MsgDIO msgDIO) {
        if (msgDIO.getMsgId() == null) {
            throw new PlatException("消息配置ID不能为空");
        }

        MsgConf msgConf = msgConfService.findByKey(msgDIO.getMsgId());
        if (msgConf == null) {
            throw new PlatException(String.format("消息ID为%s的配置未找到", msgConf.getMsgId()));
        }

        if (Objects.equals(GlobalConsts.NO, msgConf.getStatus())) {
            throw new PlatException(String.format("消息ID为%s的配置状态为停用", msgConf.getMsgId()));
        }

        List<MsgStaffSimpleVO> staffSimpleVOS = new ArrayList<>();
        staffSimpleVOS = getAllReceiveStaffSimpleVO(msgDIO);
        if (staffSimpleVOS == null || staffSimpleVOS.size() == 0) {
            throw new PlatException("接收的人员信息不能为空,请检查配置信息或者参数");
        }

        String transContent = "";
        try {
            transContent = translateParams(msgDIO, msgConf);
        } catch (Exception e) {
            logger.error("替换模板变量异常", e);
            throw new PlatException("替换模板变量异常");
        }

        if (msgConf.getSendType().indexOf(MsgConfConsts.INNER_INFO) != -1) {
            boolean sendInnerMessageSuccess = sendInnerMessage(msgDIO, msgConf, staffSimpleVOS, transContent);
            if (!sendInnerMessageSuccess) {
                throw new PlatException("发送站内信失败！");
            }
        }

        if (msgConf.getSendType().indexOf(MsgConfConsts.D_TALK_INFO) != -1) {
            boolean sendDTalkInfoSuccess = sendDingTalkMessage(msgConf, staffSimpleVOS, transContent);
            if (!sendDTalkInfoSuccess) {
                throw new PlatException("发送钉钉消息失败！");
            }
        }

        if (msgConf.getSendType().indexOf(MsgConfConsts.SHORT_MESSAGE) != -1) {
            boolean sendShortMessageSuccess = sendShortMessage(msgDIO, msgConf, staffSimpleVOS);
            if (!sendShortMessageSuccess) {
                throw new PlatException("发送短信失败！");
            }
        }

        return true;
    }

    private List<MsgStaffSimpleVO> getAllReceiveStaffSimpleVO(MsgDIO msgDIO) {
        List<Integer> staffIdList = msgDIO.getStaffIds();
        List<MsgStaffSimpleVO> staffSimpleVOS = msgConfBService.listEligibleStaffgeByMsgId(msgDIO.getMsgId());
        if (staffIdList != null && staffIdList.size() > 0) {
            ResponseDTO<List<StaffDRO>> data = staffListRemoteService.listStaffByStaffIds(staffIdList, GlobalConsts.YES);
            List<StaffDRO> staffs = null;
            if (data.isSuccess()) {
                staffs = data.getData();
            }

            if (staffs != null && staffs.size() > 0) {
                for (int i = 0; i < staffs.size(); i++) {
                    MsgStaffSimpleVO staffSimpleVO = new MsgStaffSimpleVO();
                    staffSimpleVO.setStaffId(staffs.get(i).getStaffId());
                    staffSimpleVO.setDTalkId(staffs.get(i).getDTalkId());
                    staffSimpleVO.setMobile(staffs.get(i).getMobile());
                    staffSimpleVO.setStaffNumber(staffs.get(i).getStaffNumber());
                    staffSimpleVOS.add(staffSimpleVO);
                }
            }
        }

        return staffSimpleVOS;
    }

    private String translateParams(MsgDIO msgDIO, MsgConf msgConf) throws Exception {
        String params = msgDIO.getParams();
        String[] paramArray = null;
        String resultContent = "";
        if (params != null && params != "") {
            paramArray = params.split(",");
            String msgConfContent = msgConf.getContent();
            msgConfContent = msgConfContent.replaceAll("\\{\\}", "%s");
            resultContent = String.format(msgConfContent, paramArray);
        }

        return resultContent;
    }

    boolean sendInnerMessage(MsgDIO msgDIO, MsgConf msgConf, List<MsgStaffSimpleVO> staffSimpleVOS, String transContent) {
        List<Integer> staffIdList = staffSimpleVOS.stream().map(e -> e.getStaffId()).collect(Collectors.toList());

        staffIdList = staffIdList.stream().distinct().collect(Collectors.toList());
        Map<String, String> businessDataMap = new HashMap<>();
        businessDataMap.put("linkUrl", msgConf.getLandingPage());
        businessDataMap.put("linkName", msgConf.getName());
        String businessData = JSON.toJSONString(businessDataMap);
        if (staffIdList != null && staffIdList.size() > 0) {
            List<PushInner> pushInners = new ArrayList<>();
            for (int i = 0; i < staffIdList.size(); i++) {
                PushInner pushInner = new PushInner();
                pushInner.setCreateTime(DateUtil.getNow());
                pushInner.setStatus(GlobalConsts.NO);
                pushInner.setContent(transContent);
                pushInner.setBusinessData(businessData);
                pushInner.setStaffId(staffIdList.get(i));
                pushInners.add(pushInner);
            }
            pushInfoService.insertBatch(pushInners);
            return true;
        }

        return false;
    }

    /**
     * 发送钉钉代办消息
     *
     * @param msgConf
     * @param staffSimpleVOS
     * @return
     */
    boolean sendDingTalkMessage(MsgConf msgConf, List<MsgStaffSimpleVO> staffSimpleVOS, String transContent) {
        List<String> dTalkIdList = staffSimpleVOS.stream().map(e -> e.getDTalkId()).collect(Collectors.toList());
        dTalkIdList = dTalkIdList.stream().distinct().collect(Collectors.toList());

        if (dTalkIdList != null && dTalkIdList.size() > 0) {
            for (int i = 0; i < dTalkIdList.size(); i++) {
                Date workRecordTime = DateUtil.getNow();
                String url = msgConf.getLandingPage();
                url = url + "&_title=" + msgConf.getName();

                String currentEnvUrl = getUri().get(profiles);
                if (StringUtil.isBlank(currentEnvUrl)) {
                    currentEnvUrl = getUri().get("dev");
                }
                url = currentEnvUrl + "?_href=" + url;

                String title = msgConf.getName();
                String userId = dTalkIdList.get(i);

                if (userId != null && userId.length() > 0) {
                    try {
                        dingTalkService.sendDingTalkWorkRecord(userId, workRecordTime, title, url, MsgTypeEnum.of(msgConf.getType()).getName(), transContent);
                    } catch (ApiException e) {
                        logger.error("发送钉钉代办消息失败：userId:{}", userId, e);
                    } catch (Exception e) {
                        logger.error("发送钉钉代办消息失败：userId:{}", userId, e);
                    }
                }
            }
            return true;
        }

        return false;
    }

    /**
     * 发送创蓝短信
     *
     * @param msgDIO
     * @param msgConf
     * @param staffSimpleVOS
     * @return
     */
    boolean sendShortMessage(MsgDIO msgDIO, MsgConf msgConf, List<MsgStaffSimpleVO> staffSimpleVOS) {
        List<String> mobileList = staffSimpleVOS.stream().map(e -> e.getMobile()).collect(Collectors.toList());
        mobileList = mobileList.stream().distinct().collect(Collectors.toList());
        if (mobileList != null && mobileList.size() > 0) {
            String params = "";
            StringBuilder stringBuilder = new StringBuilder();
            for (int i = 0; i < mobileList.size(); i++) {
                String mobile = mobileList.get(i);
                stringBuilder.append(mobile).append(",").append(msgDIO.getParams()).append(";");
            }
            if (stringBuilder.length() > 0) {
                params = stringBuilder.deleteCharAt(stringBuilder.length() - 1).toString();
            }
            ZmnSms zmnSms = new ZmnSms();
            zmnSms.setGroupId(msgConf.getTemplateId());
            zmnSms.setParams(params);
            Integer flag = zmnSmsService.sendZmnSmsInfo(zmnSms);
            if (!Objects.equals(flag, ZmnSmsConsts.MSG_SEND_SUCCESS)) {
                logger.error("发送短信失败：失败原因:{}", ZmnSmsDict.getErrorMsg(flag));
                return false;
            }

            return true;
        }

        return false;
    }
}
